条件分岐 ~ [[ で条件判定(ファイル)

[[ ~ ]] ファイルの演算子(よく使いそう)

test コマンドで使用できるファイルの演算子は複合コマンド [[ でも使用できます

条件 説明
-a FILEFILE が存在する( -e と同じ)
-e FILEFILE が存在する( -a と同じ)
-f FILEFILE が存在し、通常のファイルである
-d FILEFILE が存在し、ディレクトリである
-r FILEFILE が存在し、読み取り権限がある
-w FILEFILE が存在し、書き込み権限がある
-x FILEFILE が存在し、実行(または検索)権限がある
-s FILEFILE が存在し、サイズが 0 より大きい
code
# [[ -a FILE ]] | FILE が存在する
[[ -a sample1.txt ]]
echo "[[ -a sample1.txt ]] : \$?=$?"

touch sample1.txt
[[ -a sample1.txt ]]
echo "[[ -a sample1.txt ]] : \$?=$?"
stdout
[[ -a sample1.txt ]] : $?=1
[[ -a sample1.txt ]] : $?=0
code
# [[ -e FILE ]] | FILE が存在する
[[ -e sample1.txt ]]
echo "[[ -e sample1.txt ]] : \$?=$?"

touch sample1.txt
[[ -e sample1.txt ]]
echo "[[ -e sample1.txt ]] : \$?=$?"
stdout
[[ -e sample1.txt ]] : $?=1
[[ -e sample1.txt ]] : $?=0
code
touch sample1.txt
ln -s sample1.txt sample2.txt
mkdir sample1

stat -c '%A %n' *
echo '-------------------------------'

# [[ -f FILE ]] | FILE が存在し、通常のファイルである
[[ -f sample1 ]]
echo "[[ -f sample1 ]]     : \$?=$?"
[[ -f sample1.txt ]]
echo "[[ -f sample1.txt ]] : \$?=$?"
[[ -f sample2.txt ]]
echo "[[ -f sample2.txt ]] : \$?=$?"
stdout
drwxr-xr-x sample1
-rw-r--r-- sample1.txt
lrwxrwxrwx sample2.txt
-------------------------------
[[ -f sample1 ]]     : $?=1
[[ -f sample1.txt ]] : $?=0
[[ -f sample2.txt ]] : $?=0
code
touch sample1.txt
mkdir sample1
ln -s sample1 sample2

stat -c '%A %n' *
echo '-------------------------------'

# [[ -d FILE ]] | FILE が存在し、ディレクトリである
[[ -d sample1 ]]
echo "[[ -d sample1 ]]     : \$?=$?"
[[ -d sample1.txt ]]
echo "[[ -d sample1.txt ]] : \$?=$?"
[[ -d sample2 ]]
echo "[[ -d sample2 ]]     : \$?=$?"
stdout
drwxr-xr-x sample1
-rw-r--r-- sample1.txt
lrwxrwxrwx sample2
-------------------------------
[[ -d sample1 ]]     : $?=0
[[ -d sample1.txt ]] : $?=1
[[ -d sample2 ]]     : $?=0
code
touch sample1.txt sample2.txt
mkdir sample1 sample2
chmod 400 sample1.txt sample1
chmod 200 sample2.txt sample2

stat -c '%A %n' *
echo '-------------------------------'

# [[ -r FILE ]] | FILE が存在し、読み取り権限がある
[[ -r sample1 ]]
echo "[[ -r sample1 ]]     : \$?=$?"
[[ -r sample1.txt ]]
echo "[[ -r sample1.txt ]] : \$?=$?"
[[ -r sample2 ]]
echo "[[ -r sample2 ]]     : \$?=$?"
[[ -r sample2.txt ]]
echo "[[ -r sample2.txt ]] : \$?=$?"
stdout
dr-------- sample1
-r-------- sample1.txt
d-w------- sample2
--w------- sample2.txt
-------------------------------
[[ -r sample1 ]]     : $?=0
[[ -r sample1.txt ]] : $?=0
[[ -r sample2 ]]     : $?=1
[[ -r sample2.txt ]] : $?=1
code
touch sample1.txt sample2.txt
mkdir sample1 sample2
chmod 200 sample1.txt sample1
chmod 400 sample2.txt sample2

stat -c '%A %n' *
echo '-------------------------------'

# [[ -w FILE ]] | FILE が存在し、書き込み権限がある
[[ -w sample1.txt ]]
echo "[[ -w sample1.txt ]] : \$?=$?"
[[ -w sample2.txt ]]
echo "[[ -w sample2.txt ]] : \$?=$?"
stdout
d-w------- sample1
--w------- sample1.txt
dr-------- sample2
-r-------- sample2.txt
-------------------------------
[[ -w sample1.txt ]] : $?=0
[[ -w sample2.txt ]] : $?=1
code
touch sample1.txt sample2.txt
mkdir sample1 sample2
chmod 100 sample1.txt sample1
chmod 000 sample2.txt sample2

stat -c '%A %n' *
echo '-------------------------------'

# [[ -x FILE ]] | FILE が存在し、実行(または検索)権限がある
[[ -x sample1 ]]
echo "[[ -x sample1 ]]     : \$?=$?"
[[ -x sample1.txt ]]
echo "[[ -x sample1.txt ]] : \$?=$?"
[[ -x sample2 ]]
echo "[[ -x sample2 ]]     : \$?=$?"
[[ -x sample2.txt ]]
echo "[[ -x sample2.txt ]] : \$?=$?"
stdout
d--x------ sample1
---x------ sample1.txt
d--------- sample2
---------- sample2.txt
-------------------------------
[[ -x sample1 ]]     : $?=0
[[ -x sample1.txt ]] : $?=0
[[ -x sample2 ]]     : $?=1
[[ -x sample2.txt ]] : $?=1
code
printf '' > sample1.txt
printf 0  > sample2.txt

stat -c '%s %n' *
echo '-------------------------------'

# [[ -s FILE ]] | FILE が存在し、サイズが 0 より大きい
[[ -s sample1.txt ]]
echo "[[ -s sample1.txt ]] : \$?=$?"
[[ -s sample2.txt ]]
echo "[[ -s sample2.txt ]] : \$?=$?"
stdout
0 sample1.txt
1 sample2.txt
-------------------------------
[[ -s sample1.txt ]] : $?=1
[[ -s sample2.txt ]] : $?=0

[[ ~ ]] ファイルの演算子(たまに使いそう)

条件 説明
-t FD ファイル記述子 FD が端末上で開かれている
-h FILEFILE が存在し、シンボリックリンクである(-L と同じ)
-L FILEFILE が存在し、シンボリックリンクである(-h と同じ)
-N FILEFILE が存在し、最後に読み取られてから変更されている
code
# [[ -t FD ]] | ファイル記述子 FD が端末上で開かれている
tty
[[ -t 0 ]]
echo "[[ -t 0 ]] : \$?=$?"
stdout
not a tty
[[ -t 0 ]] : $?=1

端末上で [[ -t FD ]] を実行した場合は結果は 0 になります。

code
touch sample1.txt
ln -s sample1.txt sample2.txt

stat -c '%A %n' *
echo '-------------------------------'

# [[ -h FILE ]] | FILE が存在し、シンボリックリンクである(-L と同じ)
[[ -h sample1.txt ]]
echo "[[ -h sample1.txt ]] : \$?=$?"
[[ -h sample2.txt ]]
echo "[[ -h sample2.txt ]] : \$?=$?"

# [[ -L FILE ]] | FILE が存在し、シンボリックリンクである(-h と同じ)
[[ -L sample1.txt ]]
echo "[[ -L sample1.txt ]] : \$?=$?"
[[ -L sample2.txt ]]
echo "[[ -L sample2.txt ]] : \$?=$?"
stdout
-rw-r--r-- sample1.txt
lrwxrwxrwx sample2.txt
-------------------------------
[[ -h sample1.txt ]] : $?=1
[[ -h sample2.txt ]] : $?=0
[[ -L sample1.txt ]] : $?=1
[[ -L sample2.txt ]] : $?=0
code
# [[ -N FILE ]] | FILE が存在し、最後に読み取られてから変更されている
echo 'L1' >> sample1.txt

# バックグラウンドで 0.1 秒後にファイルを更新
( sleep 0.1; echo 'L2' >> sample1.txt ) &

# ファイルの読み取り
echo "$(<sample1.txt)"
# バックグラウンド処理の終了を待機
wait

[[ -N sample1.txt ]]
echo "[[ -N sample1.txt ]] : \$?=$?"
stdout
L1
[[ -N sample1.txt ]] : $?=0

[[ ~ ]] ファイルの演算子(所有者など)

条件 説明
-G FILEFILE が存在し、実行しているユーザーのグループが所有している
-O FILEFILE が存在し、実行しているユーザーが所有している
-g FILEFILE が存在し、SGID ビットが設定されている
-u FILEFILE が存在し、SUID ビットが設定されている
-k FILEFILE が存在し、スティッキービットが設定されている
code
id -a
echo '-------------------------------'
stat -c '%U:%G %A %n' /home/corp/*.txt
echo '-------------------------------'

# [[ -G FILE ]] | FILE が存在し、実行しているユーザーのグループが所有している
[[ -G /home/corp/corp.txt ]]
echo "[[ -G /home/corp/corp.txt ]] : \$?=$?"
[[ -G /home/corp/dep1.txt ]]
echo "[[ -G /home/corp/dep1.txt ]] : \$?=$?"
[[ -G /home/corp/dep2.txt ]]
echo "[[ -G /home/corp/dep2.txt ]] : \$?=$?"
stdout
uid=1000(user1) gid=100(corp) groups=100(corp),101(dep1)
-------------------------------
corp:corp -rw-r--r-- /home/corp/corp.txt
corp:dep1 -rw-r--r-- /home/corp/dep1.txt
corp:dep2 -rw-r--r-- /home/corp/dep2.txt
-------------------------------
[[ -G /home/corp/corp.txt ]] : $?=0
[[ -G /home/corp/dep1.txt ]] : $?=1
[[ -G /home/corp/dep2.txt ]] : $?=1
code
id -a
echo '-------------------------------'
stat -c '%U:%G %A %n' /home/corp/dep1/user1.txt
stat -c ' %U:%G %A %n' /home/corp/dep1.txt
echo '-------------------------------'

# [[ -O FILE ]] | FILE が存在し、実行しているユーザーが所有している
[[ -O /home/corp/dep1/user1.txt ]]
echo "[[ -O /home/corp/dep1/user1.txt ]] : \$?=$?"
[[ -O /home/corp/dep1.txt ]]
echo "[[ -O /home/corp/dep1.txt ]]       : \$?=$?"
stdout
uid=1000(user1) gid=100(corp) groups=100(corp),101(dep1)
-------------------------------
user1:dep1 -rw-r--r-- /home/corp/dep1/user1.txt
 corp:dep1 -rw-r--r-- /home/corp/dep1.txt
-------------------------------
[[ -O /home/corp/dep1/user1.txt ]] : $?=0
[[ -O /home/corp/dep1.txt ]]       : $?=1
code
stat -c '%U:%G %A %n' /home/corp/dep1
stat -c '%U:%G %A %n' /home/corp/dep1/share
echo '-------------------------------'

# [[ -g FILE ]] | FILE が存在し、SGID ビットが設定されている
[[ -g /home/corp/dep1 ]]
echo "[[ -g /home/corp/dep1 ]]       : \$?=$?"
[[ -g /home/corp/dep1/share ]]
echo "[[ -g /home/corp/dep1/share ]] : \$?=$?"
stdout
corp:dep1 drwxr-xr-x /home/corp/dep1
corp:dep1 drwxr-sr-x /home/corp/dep1/share
-------------------------------
[[ -g /home/corp/dep1 ]]       : $?=1
[[ -g /home/corp/dep1/share ]] : $?=0
code
stat -c '%U:%G %A %n' /home/corp/corp.sh
echo '-------------------------------'

# [[ -u FILE ]] | FILE が存在し、SUID ビットが設定されている
[[ -u /home/corp/corp.sh ]]
echo "[[ -u /home/corp/corp.sh ]] : \$?=$?"
stdout
corp:corp -rwsr-xr-x /home/corp/corp.sh
-------------------------------
[[ -u /home/corp/corp.sh ]] : $?=0
code
stat -c '%U:%G %A %n' /tmp
echo '-------------------------------'

# [[ -k FILE ]] | FILE が存在し、スティッキービットが設定されている
[[ -k /tmp ]]
echo "[[ -k /tmp ]] : \$?=$?"
stdout
root:root drwxrwxrwt /tmp
-------------------------------
[[ -k /tmp ]] : $?=0

[[ ~ ]] ファイルの比較

条件 説明
FILE1 -ef FILE2FILE1 と FILE2 が同じデバイス番号と iノード番号を参照している
FILE1 -nt FILE2FILE1 が FILE2 より更新日が新しい、または FILE1 が存在し FILE2 が存在しない
FILE1 -ot FILE2FILE1 が FILE2 より更新日が古い、または FILE2 が存在し FILE1 が存在しない
code
touch sample1.txt
touch sample2.txt
ln sample1.txt sample3.txt
stat -c 'device=%d inode=%i %n' *
echo '-------------------------------'

# [[ FILE1 -ef FILE2 ]] | FILE1 と FILE2 が同じデバイス番号と iノード番号を参照している
[[ sample1.txt -ef sample2.txt ]]
echo "[[ sample1.txt -ef sample2.txt ]] : \$?=$?"
[[ sample1.txt -ef sample3.txt ]]
echo "[[ sample1.txt -ef sample3.txt ]] : \$?=$?"
stdout
device=46 inode=3969508 sample1.txt
device=46 inode=3969494 sample2.txt
device=46 inode=3969508 sample3.txt
-------------------------------
[[ sample1.txt -ef sample2.txt ]] : $?=1
[[ sample1.txt -ef sample3.txt ]] : $?=0
code
touch -d '2023-01-01' sample1.txt
touch -d '2023-01-01' sample2.txt
touch -d '2023-01-01' sample3.txt
touch -d '2023-01-02' -m sample2.txt
stat -c 'ctime=%W mtime=%Y %n' *
echo '-------------------------------'

# [[ FILE1 -nt FILE2 ]] | FILE1 が FILE2 より更新日が新しい、または FILE1 が存在し FILE2 が存在しない
[[ sample1.txt -nt sample2.txt ]]
echo "[[ sample1.txt -nt sample2.txt ]] : \$?=$?"
[[ sample2.txt -nt sample3.txt ]]
echo "[[ sample2.txt -nt sample3.txt ]] : \$?=$?"
[[ sample1.txt -nt sample4.txt ]]
echo "[[ sample1.txt -nt sample4.txt ]] : \$?=$?"
[[ sample4.txt -nt sample1.txt ]]
echo "[[ sample4.txt -nt sample1.txt ]] : \$?=$?"
stdout
ctime=1717283168 mtime=1672531200 sample1.txt
ctime=1717283168 mtime=1672617600 sample2.txt
ctime=1717283168 mtime=1672531200 sample3.txt
-------------------------------
[[ sample1.txt -nt sample2.txt ]] : $?=1
[[ sample2.txt -nt sample3.txt ]] : $?=0
[[ sample1.txt -nt sample4.txt ]] : $?=0
[[ sample4.txt -nt sample1.txt ]] : $?=1
code
touch -d '2023-01-01' sample1.txt
touch -d '2023-01-01' sample2.txt
touch -d '2023-01-01' sample3.txt
touch -d '2023-01-02' -m sample2.txt
stat -c 'ctime=%W mtime=%Y %n' *
echo '-------------------------------'

# [[ FILE1 -ot FILE2 ]] | FILE1 が FILE2 より更新日が古い、または FILE2 が存在し FILE1 が存在しない
[[ sample1.txt -ot sample2.txt ]]
echo "[[ sample1.txt -ot sample2.txt ]] : \$?=$?"
[[ sample2.txt -ot sample3.txt ]]
echo "[[ sample2.txt -ot sample3.txt ]] : \$?=$?"
[[ sample1.txt -ot sample4.txt ]]
echo "[[ sample1.txt -ot sample4.txt ]] : \$?=$?"
[[ sample4.txt -ot sample1.txt ]]
echo "[[ sample4.txt -ot sample1.txt ]] : \$?=$?"
stdout
ctime=1717283168 mtime=1672531200 sample1.txt
ctime=1717283168 mtime=1672617600 sample2.txt
ctime=1717283168 mtime=1672531200 sample3.txt
-------------------------------
[[ sample1.txt -ot sample2.txt ]] : $?=0
[[ sample2.txt -ot sample3.txt ]] : $?=1
[[ sample1.txt -ot sample4.txt ]] : $?=1
[[ sample4.txt -ot sample1.txt ]] : $?=0

[[ ~ ]] ファイルの演算子(特殊なファイル)

条件 説明
-S FILEFILE が存在し、ソケットファイルである
-b FILEFILE が存在し、ブロックデバイスファイルである
-c FILEFILE が存在し、キャラクタデバイスァイルである
-p FILEFILE が存在し、名前付きパイプファイルである